package com.central.apps.service.impl;

import com.central.app.common.cache.CfgRedisCache;
import com.central.app.common.util.AppCommonUtil;
import com.central.app.dao.CommonDao;
import com.central.app.model.BizApp;
import com.central.app.model.BizObject;
import com.central.app.model.CommonModel;
import com.central.apps.service.ProjectCostService;
import com.central.common.util.ToolUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 项目管理成本接口实现类
 *
 * @author 李大超
 * @date 2023/1/30
 */
@Slf4j
@Service
public class ProjectCostServiceImpl implements ProjectCostService {

    @Autowired
    private CfgRedisCache cfgRedisCache;
    @Autowired
    private CommonDao commonDao;

    /**
     * 查询{app}树
     *
     * @param app
     * @param params
     * @param isPermission
     * @return List
     */
    @Override
    public List<Map<String, Object>> costTree(String app, Map<String, Object> params, boolean isPermission) throws Exception {
        String treeId = MapUtils.getString(params,"tree_id");
        String treePid = MapUtils.getString(params,"tree_pid");
        String proid_wheres = MapUtils.getString(params,"proid_wheres");

        if (StringUtils.isEmpty(treeId) || StringUtils.isEmpty(treePid) || StringUtils.isEmpty(proid_wheres)) {
            return null;
        }

        // 初始化父级查询条件
        params.put("where_condition", "(" + treePid + " is null or " + treePid + " = 0)");

        // 获取对象信息
        BizObject bizObject = cfgRedisCache.getCacheObjByApp(app);
        // 获取应用信息
        BizApp bizApp = cfgRedisCache.getCacheApp(app);

        // 组织查询模型
        CommonModel commonModel = combineModel(bizObject, bizApp, params);

        // 查询树形父级数据
        List<Map<String, Object>> dataList = commonDao.findList(commonModel);

        // 转换结果集
        List<Map<String, Object>> resultList = convertList(dataList);

        // 清楚父级查询条件
        params.remove("where_condition");

        // 递归查询树形子级数据
        recursiveQuery(bizObject, bizApp, params, resultList, treeId, treePid);

        return resultList;
    }

    /**
     * 项目成本树
     *
     * @param app
     * @param params
     * @param isPermission
     * @return List
     */
    @Override
    public List<Map<String, Object>> costStatisticTree(String app, Map<String, Object> params, boolean isPermission) throws Exception {
        String treeId = MapUtils.getString(params,"tree_id");
        String treePid = MapUtils.getString(params,"tree_pid");
        String proid_wheres = MapUtils.getString(params,"proid_wheres");

        if (StringUtils.isEmpty(treeId) || StringUtils.isEmpty(treePid) || StringUtils.isEmpty(proid_wheres)) {
            return null;
        }

        // 初始化父级查询条件
        params.put("where_condition", "(" + treePid + " is null or " + treePid + " = 0)");

        // 获取对象信息
        BizObject bizObject = cfgRedisCache.getCacheObjByApp(app);
        // 获取应用信息
        BizApp bizApp = cfgRedisCache.getCacheApp(app);

        // 组织查询模型
        CommonModel commonModel = combineModel(bizObject, bizApp, params);

        // 查询树形父级数据
        List<Map<String, Object>> dataList = commonDao.findList(commonModel);

        // 转换结果集
        List<Map<String, Object>> resultList = convertStatisticList(dataList);

        // 清楚父级查询条件
        params.remove("where_condition");

        // 递归查询树形子级数据
        recursiveStatisticQuery(bizObject, bizApp, params, resultList, treeId, treePid);

        return resultList;
    }

    @Override
    public void updProExecuteCost(Integer proId) throws Exception {
        List<Map<String, Object>> list = commonDao.findBySql("select budgetamt, usefulamt from gq_pblbestimate where proid = " + proId);
        if (CollectionUtils.isNotEmpty(list)) {
            BigDecimal totalBudgetAmt = BigDecimal.ZERO;
            BigDecimal totalUsedAmt = BigDecimal.ZERO;

            for (Map<String, Object> map : list) {
                String budgetAmtStr = MapUtils.getString(map, "budgetamt");
                String usefulAmtStr = MapUtils.getString(map, "usefulamt");

                BigDecimal budgetAmt = new BigDecimal(budgetAmtStr);
                BigDecimal usefulAmt = new BigDecimal(usefulAmtStr);

                totalBudgetAmt = totalBudgetAmt.add(budgetAmt);
                totalUsedAmt = totalUsedAmt.add(budgetAmt.subtract(usefulAmt));
            }

            if (totalUsedAmt.compareTo(totalBudgetAmt) < 0) {
                // 计算成本执行比例
                BigDecimal executeRatio = totalUsedAmt.multiply(BigDecimal.valueOf(100)).divide(totalBudgetAmt, 0, BigDecimal.ROUND_CEILING);

                // 更新项目信息
                commonDao.updateBySql("update gq_proaccount set bexecuteratio = " + executeRatio + " where id = " + proId);
            }
        }
    }

    @Override
    public void updProPlanExecuteCost(Integer proId) throws Exception {
        List<Map<String, Object>> planList = commonDao.findBySql("select year from gq_proplan where bexecuteratio < 100 and proid = " + proId);

        if (CollectionUtils.isNotEmpty(planList)) {
            for (Map<String, Object> planMap : planList) {
                Integer id = MapUtils.getInteger(planMap, "id");
                String year = MapUtils.getString(planMap, "year");

                List<Map<String, Object>> list = commonDao.findBySql("select budgetamt, usefulamt from gq_probudget where proid = " + proId + " and year = '" + year + "'");
                if (CollectionUtils.isNotEmpty(list)) {
                    BigDecimal totalBudgetAmt = BigDecimal.ZERO;
                    BigDecimal totalUsedAmt = BigDecimal.ZERO;

                    for (Map<String, Object> map : list) {
                        String budgetAmtStr = MapUtils.getString(map, "budgetamt");
                        String usefulAmtStr = MapUtils.getString(map, "usefulamt");

                        BigDecimal budgetAmt = new BigDecimal(budgetAmtStr);
                        BigDecimal usefulAmt = new BigDecimal(usefulAmtStr);

                        totalBudgetAmt = totalBudgetAmt.add(budgetAmt);
                        totalUsedAmt = totalUsedAmt.add(budgetAmt.subtract(usefulAmt));
                    }

                    if (totalUsedAmt.compareTo(totalBudgetAmt) < 0) {
                        // 计算成本执行比例
                        BigDecimal executeRatio = totalUsedAmt.divide(totalBudgetAmt, 0, BigDecimal.ROUND_CEILING);

                        // 更新项目实施策划信息
                        commonDao.updateBySql("update gq_proplan set bexecuteratio = " + executeRatio + " where id = " + id);
                    }
                }
            }
        }
    }

    /**
     * 递归查询树形子级数据
     *
     * @param dataList
     */
    private void recursiveQuery(BizObject bizObject, BizApp bizApp, Map<String, Object> params,
                                List<Map<String, Object>> dataList, String treeId, String treePid) throws Exception {
        for (Map<String, Object> dataMap : dataList) {
            Integer id = MapUtils.getInteger(dataMap, "tempid");

            if (id == null) {
                continue;
            }

            params.put("where_condition", "(" + treePid + " = " + id + ")");

            // 初始化子级查询条件
            CommonModel commonModel = combineModel(bizObject, bizApp, params);

            // 查询树形子级数据
            List<Map<String, Object>> childList = commonDao.findList(commonModel);

            // 转换结果集
            List<Map<String, Object>> resultList = convertList(childList);

            // 清楚子级查询条件
            params.remove("where_condition");

            // 查询成本项信息
            List<Map<String, Object>> costElements = commonDao.findBySql("select '——' as name, '' as totalcost, a.id as parentid, t.id, t.proid, t.costcategory, t.costitem, " +
                    " t.calculateway, t.costsource, ifnull(t.budgetamt, 0) as budgetamt from gq_procostelements t left join gq_procoststructure a on a.id = t.pcsid where pcsid = " + id);

            if (CollectionUtils.isNotEmpty(costElements)) {
                resultList.addAll(costElements);
            }

            if (CollectionUtils.isNotEmpty(resultList)) {
                dataMap.put("children", resultList);

                // 递归树形子级数据
                recursiveQuery(bizObject, bizApp, params, resultList, treeId, treePid);
            }
        }
    }

    /**
     * 转换成统一实体名称
     *
     * @param dataList
     * @return
     */
    private List<Map<String, Object>> convertList(List<Map<String, Object>> dataList) {
        List<Map<String, Object>> resultList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(dataList)) {
            int i = -1;
            for (Map<String, Object> map : dataList) {
                Map<String, Object> resultMap = new HashMap<>();
                resultMap.put("id", i);
                resultMap.put("parentid", map.get("parentid"));
                resultMap.put("proid", map.get("proid"));
                resultMap.put("name", map.get("name"));
                resultMap.put("costitem", "");
                resultMap.put("totalcost", map.get("totalcost"));
                resultMap.put("costcategory", "");
                resultMap.put("costsource", "");
                resultMap.put("calculateway", "");
                resultMap.put("budgetamt", "");
                resultMap.put("tempid", map.get("id"));

                resultList.add(resultMap);

                i--;
            }
        }

        return resultList;
    }

    /**
     * 递归查询树形子级数据
     *
     * @param dataList
     */
    private void recursiveStatisticQuery(BizObject bizObject, BizApp bizApp, Map<String, Object> params,
                                List<Map<String, Object>> dataList, String treeId, String treePid) throws Exception {
        for (Map<String, Object> dataMap : dataList) {
            Integer id = MapUtils.getInteger(dataMap, "tempid");

            if (id == null) {
                continue;
            }

            params.put("where_condition", "(" + treePid + " = " + id + ")");

            // 初始化子级查询条件
            CommonModel commonModel = combineModel(bizObject, bizApp, params);

            // 查询树形子级数据
            List<Map<String, Object>> childList = commonDao.findList(commonModel);

            // 转换结果集
            List<Map<String, Object>> resultList = convertStatisticList(childList);

            // 清楚子级查询条件
            params.remove("where_condition");

            // 查询成本项信息
            List<Map<String, Object>> costElements = commonDao.findBySql("select t.costitem as name, a.id as parentid, t.id, t.proid, ifnull(t.budgetamt, 0) as budgetamt, " +
                    " ifnull(t.actualamt, 0) as actualamt, ifnull(t.finishpercent, 0) as finishpercent, ifnull(t.differenceamt, 0) as differenceamt, ifnull(t.usefulamt, 0) as usefulamt from gq_procostelements t left join gq_procoststructure a on a.id = t.pcsid where pcsid = " + id);

            if (CollectionUtils.isNotEmpty(costElements)) {
                resultList.addAll(costElements);
            }

            if (CollectionUtils.isNotEmpty(resultList)) {
                dataMap.put("children", resultList);

                // 递归树形子级数据
                recursiveStatisticQuery(bizObject, bizApp, params, resultList, treeId, treePid);
            }
        }
    }

    /**
     * 转换成统一实体名称
     *
     * @param dataList
     * @return
     */
    private List<Map<String, Object>> convertStatisticList(List<Map<String, Object>> dataList) {
        List<Map<String, Object>> resultList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(dataList)) {
            for (Map<String, Object> map : dataList) {
                Map<String, Object> resultMap = new HashMap<>();
                resultMap.put("id", map.get("id"));
                resultMap.put("parentid", map.get("parentid"));
                resultMap.put("proid", map.get("proid"));
                resultMap.put("name", map.get("name"));
                resultMap.put("budgetamt", map.get("budgetamt"));
                resultMap.put("actualamt", map.get("actualamt"));
                resultMap.put("finishpercent", map.get("finishpercent"));
                resultMap.put("differenceamt", map.get("differenceamt"));
                resultMap.put("usefulamt", map.get("usefulamt"));
                resultMap.put("tempid", map.get("id"));
                resultList.add(resultMap);
            }
        }

        return resultList;
    }

    /**
     * 组织查询模型
     *
     * @param bizObject
     * @param bizApp
     * @param params
     * @return CommonModel
     * @throws Exception
     */
    private CommonModel combineModel(BizObject bizObject, BizApp bizApp, Map<String, Object> params) throws Exception {
        CommonModel commonModel = new CommonModel();
        AppCommonUtil.setFindParams(commonModel, params, bizApp, bizObject);

        Map<String,Object> wheresMap = commonModel.getWhereEqs();
        if(ToolUtil.isNotEmpty(wheresMap)){
            for(Map.Entry<String, Object> entry : wheresMap.entrySet()){
                if(StringUtils.isEmpty(entry.getValue().toString())){
                    wheresMap.remove(entry.getValue());
                }
            }
        }

        return commonModel;
    }
}
